package com.zjny.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.alibaba.excel.read.metadata.holder.ReadRowHolder;
import com.zjny.pojo.BaseExcel;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * packageName com.zjny.listener
 * 自定义excel监听器
 * 泛型类型必须是BaseExcel的扩展类
 *
 * @author cui haida
 * @version JDK 8
 * 2025/6/18
 */
@Getter
@Slf4j
public class ReadExcelListener<T extends BaseExcel> extends AnalysisEventListener<T> {

    /**
     * 数据整合 - 存储读取到的数据
     */
    private final List<T> list = new ArrayList<>();
    /**
     * 表头集合 - 存储读取到的表头, Map key is columnIndex, value is columnName
     */
    private final List<Map<Integer, String>> headMapList = new ArrayList<>();

    /**
     * 读取数据
     * 这个每一条数据解析都会来调用
     *
     * @param data     数据
     * @param context  上下文
     */
    @Override
    public void invoke(T data, AnalysisContext context) {
        // 获取行号
        ReadRowHolder readRowHolder = context.readRowHolder();
        // 设置行号并写入到list中
        data.setRowIndex(readRowHolder.getRowIndex());
        list.add(data);
    }

    /**
     * 加入到表头集合
     * @param headMap 表头map
     * @param context 上下文
     */
    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        headMapList.add(headMap);
    }

    /**
     * 所有数据解析完成了 都会来调用, 清空数据
     *
     * @param context 上下文
     */
    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        log.info("所有数据解析完成");
        list.clear();
        headMapList.clear();
    }

    /**
     * 当处理数据时发生异常时的处理逻辑。
     *
     * @param exception 异常对象，封装了在数据处理过程中发生的异常信息。
     * @param context 分析上下文，提供了当前处理的上下文环境信息。
     * @throws Exception 如果异常类型为 ExcelDataConvertException，则抛出运行时异常，
     *                   否则根据异常类型进行相应的处理或向上抛出异常。
     */
    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        if (exception instanceof ExcelDataConvertException) {
            // 计算出错的列索引和行索引，并生成对应的错误提示信息
            int columnIndex = ((ExcelDataConvertException) exception).getColumnIndex() + 1;
            int rowIndex = ((ExcelDataConvertException) exception).getRowIndex() + 1;
            String message = "第" + rowIndex + "行，第" + columnIndex + "列" + "数据格式有误，请核实";
            throw new RuntimeException(message);
        } else if (exception instanceof RuntimeException) {
            // 直接抛出运行时异常
            throw exception;
        } else {
            // 对于其他类型的异常，调用父类的异常处理方法
            super.onException(exception, context);
        }
    }


}
